from constant.param_config import getConfigPath, getImmediatelyTime
from constant.globl_constant import strategyList, mvSingal, indicatorSignal
from utils.crawl_tool_for_py3_v6 import crawlerTool
from utils.db_util import SqliteTool
from utils.log_util import saveLog, prints
# from worker.base_worker import BaseWorker
from utils.e_mail import sendMail
# from utils.qianfan_util import QianFan
from utils.time_util import MMDDHHMM2, stamp_time, today_hour_stamp, current_time
from collections import Counter
import datetime
import difflib
import threading
import time
import json
import re


class ArticleWorker():

    regularList = [
        "黄金操作(策略|思路|建议)[^;；。！!]*[;；。！!]",
        "(综合来看|综上所述|综合考虑)[^;；。！!]*[;；。！!]",
        "(?:黄金)?晚间[(操作)|(交易)][^!！;；。]*[!！;；。]",
        "日内短线[^！!。]*[^！!。]",
        "日内操作[^！!。]*[^！!。]",
        "今日晚间[^！!。]*[^！!。]",
        "黄金晚间[^！!。：]*[^！!。：]",
        "操作建议[^！!]*策略[^！!。]*[！!。]",
        "操作建议[^！!。]*[^！!。]",
        "策略建议[^！!。]*[^！!。]",
        "今日操作[^！!。]*[^！!。]",
        "(对于晚间，|对于今日，)[^！!。]*[^！!。]",
        "后市操作上[^！!。]*[^！!。]",
        "黄金[^！!]*策略[^！!。]*[！!。]",
        "[，！!。][^，！!；;。]*不破做空[^！!；;]*不破做多[^！!；;。]*[！!；;。]",
        "(操作[上]?建议|操作思路上|操作方面)[^!！;；。]*[!！;；。]",
        "今日：[^！!。]*[！!。]",
        "策略一：[^；]*[；]",
        "日内[^！!。]*(空|多|损|目标)[^！!。]*(空|多|损|目标)[^！!。]*(空|多|损|目标)*[^！!。]",
        "今日而言[^!！;；。]*上方[^!！;；]*下方[^!！;；。]*[!！;；。]",
        "今天[^！!；;]*[空|多][^！!；;]*[！!；;。]",
        "[^！!。]*(附近多|止损|目标)[^！!。]*(附近多|止损|目标)[^！!。]*(目标|附近多|止损)[^！!。]",
        "[^！!。]*(关注|止损|入场|支撑|压力)[^！!。]*(关注|止损|入场|支撑|压力)[^！!。]*(入场|关注|止损|支撑|压力)*[^！!。]",
    ]

    sellRegularList = [
        "反弹至\d{4}-\d{4}[^;；。！!，，]*(做)?空",
        "\d{4}-\d{4}[^;；。！!，，]*(做)?空",
        "\d{4}-\d{2}[^;；。！!，，]*(做)?空",
        "\d{4}[^;；。！!，，]*(做)?空",
        "\d{4}-\d{4}[^;；。！!，，((]*(阻力|卖出)",
        "\d{4}-\d{2}[^;；。！!，，]*阻力",
        "\d{4}[^;；。！!，，:：（(]*(卖|下游|跌|阻力)",
        "[^，！!；;。]*空单[^;；。！!，，]*进场[^;；。！!，，]*\d{4}-\d{4}",
        "(压力|看下方)[^;；。！!，，]*\d{4}-\d{4}",
        "做空[^;；。！!，，]*\d{4}-\d{2}",
        "(做空|阻力)[^;；。！!，，]*\d{4}",
        "上方[^;；。！!，，]*\d{4}不破",
        "\d{4}[^;；。！!，，]*不破看(下行|跌)",
    ]
    buyRegularList = [
        "反弹至\d{4}-\d{4}[^;；。！!，，]*(做)?多",
        "\d{4}-\d{4}[^;；。！!，，]*(做)?多",
        "\d{4}-\d{2}[^;；。！!，，]*(做)?多",
        "\d{4}[^;；。！!，，]*(做)?多",
        "\d{4}-\d{4}[^;；。！!，，（(]*(支撑|买)",
        "\d{4}-\d{2}[^;；。！!，，]*支撑",
        "\d{4}[^;；。！!，，:：（(]*(买|上游|涨|支撑)",
        "[^，！!；;。]*多单[^;；。！!，，]*进场[^;；。！!，，]*\d{4}-\d{4}",
        "(支撑|看上方)[^;；。！!，，]*\d{4}-\d{4}",
        "做多[^;；。！!，，]*\d{4}-\d{2}",
        "(做多|支撑)[^;；。！!，，]*\d{4}",
        "下方[^;；。！!，，]*\d{4}不破",
        "\d{4}[^;；。！!，，]*不破看(上行|涨)",
    ]
    stopLossRegularList = [
        "(止损|保护|防守)\d{4}",
        "sun[^;；。！!，，]*\d{1}个点",
    ]
    takeProfitRegularList = [
        "(目标|下看)[^;；。！!，，]*\d{4}-\d{4}一线",
        "(目标|下看)[^;；。！!，，]*\d{4}-\d{4}",
        "(目标|下看)[^;；。！!，，]*\d{4}",
        "(空|多)到[^;；。！!，，]*\d{4}",
    ]

    coreBuy = ["多为主", "涨为主", "空为辅", "先多后空", "主多", "看多"]
    coreSell = ["空为主", "多为辅", "先空后多", "主空", "看空"]

    immediately = ["现价[^！!。，]\d{4}[^！!。，](多|空)"]

    noStrategy = []
    strategyInfoList = []
    coreResult = None
    timePoint = [9, 12, 15, 18, 21]

    maxStrategyLength = 300

    webSite = "https://pinglun.fx678.com"
    articePath = webSite + "/category/103?page="
    lastDay = -1
    page = 1

    def __init__(self):
        super().__init__()
        # self.loginState = self.mqlLogin()
        self.request = crawlerTool()
        # self.qianfan = QianFan()

    def startThread(self):
        thread = threading.Thread(target=self.execution, args=(self.page, ))
        thread.start()

    def execution(self, page):
        """
        初始化数据库
        """
        prints("文章爬虫服务已启动...")

        tables = ["article_table", "record_table"]
        dbPath = getConfigPath() + "\data.db"

        self.sqlite = SqliteTool(dbPath=dbPath)
        self.sqlite.create_table_list(tableName=tables)

        while True:
            # if self.marketClose() is False:
            if True:
                timeNow = datetime.datetime.now().hour
                if self.lastDay != timeNow and (self.lastDay == -1 or timeNow in self.timePoint or (self.isHasStrategy() is False and timeNow <= 23)):
                    if self.lastDay == -1 or timeNow == 9:
                        self.updateRecord()
                        self.sqlite.delete_record("DELETE FROM article_table")
                    self.lastDay = timeNow

                    self.startTime = self.getArticleTime()
                    saveLog("开始获取网络策略...")
                    self.getWebInfo(page)
                    self.regularStrategy()
                    self.regularViewpoint()
                    self.priceInfo()
                    saveLog("网络策略获取结束")
            else:
                self.initSingal()
            time.sleep(60*10)

    def getWebInfo(self, page):
        """
        1、爬取文章url
        """
        response = self.request.get(self.articePath + str(page))
        listItem = crawlerTool.getXpath(
            '//li[@class="category-list__item clearfix"]', response)
        for index in range(0, len(listItem)):
            try:
                item = listItem[index]
                time = crawlerTool.getXpath(
                    '//span[@class="category-list__time"]/text()', item)
                currentStamp = stamp_time(time[0], MMDDHHMM2)

                if currentStamp <= self.startTime:
                    break

                url = self.webSite + crawlerTool.getXpath('//a/@href', item)[0]
                maxId = self.sqlite.query_one(
                    "SELECT MAX(id) FROM article_table")
                id = 0
                if len(maxId) != 0 and maxId[0] is not None:
                    id = maxId[0] + 1
                self.sqlite.operate_one(
                    'insert into article_table values(?,?,?,?,?,?)',
                    (id, url, "", "", "", currentStamp))
            except Exception as e:
                saveLog("序号" + str(item[0]) + "url解析错误")

            if index == len(listItem) - 1:
                page = page + 1
                self.getWebInfo(page)

        if page <= 2:
            self.pageContent()

    def pageContent(self):
        """
        2、爬取文章内容
        """
        newArticle = self.sqlite.query_many(
            "SELECT id,url,time FROM article_table WHERE article = '' and time > "+str(self.startTime))

        if newArticle is not None and len(newArticle) != 0:
            for item in newArticle:
                try:
                    content = self.request.get(item[1])
                    article = crawlerTool.getXpath('//div[@class="article-cont"]',
                                                   content)

                    results = crawlerTool.getXpath(
                        '//p/strong/text()', article[0])
                    if len(results) == 0:
                        results = crawlerTool.getXpath(
                            '//p/text()', article[0])
                    value = re.sub(r"\s+", "", "".join(results))

                    sameContent = []
                    contentList = self.sqlite.query_many(
                        "SELECT article FROM article_table WHERE article != ''")
                    if contentList is not None and len(contentList) != 0:
                        sameContent = [
                            item for item in contentList if difflib.SequenceMatcher(
                                None, item[0], value).quick_ratio() > 0.9
                        ]
                    if len(sameContent) == 0:
                        self.sqlite.operate_one(
                            "update article_table set article=? where id=?",
                            (value, item[0]))

                        # 现价单
                        self.immediatelyTrade(value, item[2])
                except Exception as e:
                    saveLog("序号" + str(item[0]) + "文章内容解析错误")
                time.sleep(3)

    def regularStrategy(self):
        """
        3、正则匹配交易策略
        """

        articleList = self.sqlite.query_many(
            "SELECT id,article FROM article_table WHERE  article != '' and time > "+str(self.startTime))

        if articleList is not None and len(articleList) != 0:
            for item in articleList:
                reResult = []
                for index in range(0, len(self.regularList)):
                    result_ti = re.search(
                        self.regularList[index], item[1], re.S)
                    if result_ti and len(result_ti.group()) < self.maxStrategyLength:
                        reslit = result_ti.group()

                        if ("策略一" in reslit and "策略二" not in reslit) or ("策略1" in reslit and "策略2" not in reslit):
                            childStr = item[1][item[1].find(
                                reslit)+len(reslit):]
                            if childStr != "" and childStr != None:
                                childResult = re.search(
                                    "(策略二|策略2)[^！!。；]*[^！!。；]", childStr, re.S)
                                if childResult:
                                    reslit = reslit+childResult.group()

                        childResult = re.search("\d{4}", reslit, re.S)
                        if childResult:
                            reResult.append(reslit)

                if len(reResult) != 0:
                    minLengthStr = min(reResult, key=len)
                    self.sqlite.operate_one(
                        "update article_table set strategy=? where id=?",
                        (minLengthStr, item[0]))

    def regularViewpoint(self):
        """
        4、匹配交易观点
        """

        if self.hasNewArticle() is False:
            return

        self.strategyInfoList.clear()
        strategys = self.sqlite.query_many(
            "SELECT id,strategy FROM article_table WHERE strategy != ''")

        if strategys is not None and len(strategys) != 0:
            for item in strategys:
                childStrategy = []
                for index in range(0, len(self.sellRegularList)):
                    sell = {}
                    result = re.search(
                        self.sellRegularList[index], item[1], re.S)
                    if result:
                        sell["sell"] = self.formatePrice(result.group())
                        for spItem in self.stopLossRegularList:
                            spResult = re.search(spItem, item[1], re.S)
                            if spResult:
                                reslit = spResult.group()
                                sell["sp"] = self.formatePrice(reslit)
                                break
                        for tpItem in self.takeProfitRegularList:
                            tpResult = re.search(tpItem, item[1], re.S)
                            if tpResult:
                                reslit = tpResult.group()
                                sell["tp"] = self.formatePrice(reslit)
                                break
                    if len(sell) != 0:
                        childStrategy.append(sell)
                        break
                    elif index == len(self.sellRegularList) - 1:
                        break

                for index in range(0, len(self.buyRegularList)):
                    buy = {}
                    result = re.search(
                        self.buyRegularList[index], item[1], re.S)
                    if result:
                        buy["buy"] = self.formatePrice(result.group())
                        for spItem in self.stopLossRegularList:
                            spResult = re.search(spItem, item[1], re.S)
                            if spResult:
                                reslit = spResult.group()
                                buy["sp"] = self.formatePrice(reslit)
                                break
                        for tpItem in self.takeProfitRegularList:
                            tpResult = re.search(tpItem, item[1], re.S)
                            if tpResult:
                                reslit = tpResult.group()
                                buy["tp"] = self.formatePrice(reslit)
                                break
                    if len(buy) != 0:
                        childStrategy.append(buy)
                        break
                    elif index == len(self.buyRegularList) - 1:
                        break

                if len(childStrategy) != 0:
                    info = self.formatePriceList([childStrategy])
                    self.strategyInfoList.append(info[0])
                    self.sqlite.operate_one(
                        "update article_table set viewpoint=? where id=?",
                        (json.dumps(info[0]), item[0]))
                else:
                    self.noStrategy.append(item[1])
                    self.sqlite.operate_one(
                        "update article_table set viewpoint=? where id=?",
                        ("", item[0]))

    def coreStrategy(self, strategy):
        """
        5、核心策略
        """
        if strategy is None or len(strategy) < 10:
            return None

        stateArr = []
        buySize = 0
        sellSize = 0
        for item in strategy:
            findNext = True
            for index in range(0, len(self.coreSell)):
                if self.coreSell[index] in item[1]:
                    stateArr.append(1)
                    findNext = False
                    break

            if findNext:
                for index in range(0, len(self.coreBuy)):
                    if self.coreBuy[index] in item[1]:
                        stateArr.append(2)
                        break
        if len(stateArr) != 0:
            sellSize = [item for item in stateArr if item == 1]
            buySize = [item for item in stateArr if item == 2]
            if len(sellSize) / len(stateArr) > 0.6:
                return "sell"
            elif len(buySize) / len(stateArr) > 0.6:
                return "buy"
        return None

    def priceInfo(self):
        """
        6、获取详细的策略价格
        """

        if self.hasNewArticle() is False:
            saveLog("无新文章发布")
            return

        sellPrice = []
        sellTpPrice = []
        sellSpPrice = []

        buyPrice = []
        buyTpPrice = []
        buySpPrice = []

        strategyList.clear()
        for child in self.strategyInfoList:
            sellIndex = [
                index for index in range(0, len(child))
                if "sell" in child[index]
            ]
            buyIndex = [
                index for index in range(0, len(child))
                if "buy" in child[index]
            ]

            if len(sellIndex) != 0:
                sellInfo = child[sellIndex[0]]
                sellPrice.extend(
                    [int(item) for item in sellInfo["sell"].split("、")])
                if "sp" in sellInfo and sellInfo["sp"] != "":
                    sellSpPrice.extend(
                        [int(item) for item in sellInfo["sp"].split("、")])
                if "tp" in sellInfo and sellInfo["tp"] != "":
                    sellTpPrice.extend(
                        [int(item) for item in sellInfo["tp"].split("、")])

            if len(buyIndex) != 0:
                buyInfo = child[buyIndex[0]]
                buyPrice.extend(
                    [int(item) for item in buyInfo["buy"].split("、")])
                if "sp" in buyInfo and buyInfo["sp"] != "":
                    buySpPrice.extend(
                        [int(item) for item in buyInfo["sp"].split("、")])
                if "tp" in buyInfo and buyInfo["tp"] != "":
                    buyTpPrice.extend(
                        [int(item) for item in buyInfo["tp"].split("、")])

        if len(self.strategyInfoList) != 0:
            sellPriceSorted = sorted(sellPrice, reverse=True)
            sellTpPriceSorted = sorted(sellTpPrice, reverse=True)
            sellSpPriceSorted = sorted(sellSpPrice, reverse=True)
            buyPriceSorted = sorted(buyPrice, reverse=True)
            buyTpPriceSorted = sorted(buyTpPrice, reverse=True)
            buySpPriceSorted = sorted(buySpPrice, reverse=True)

            headSellPrice = sorted(
                [item[0] for item in Counter(sellPriceSorted).most_common(3)])
            headSellTpPrice = sorted(
                [item[0] for item in Counter(sellTpPriceSorted).most_common(3)])
            headSellSpPrice = sorted(
                [item[0] for item in Counter(sellSpPriceSorted).most_common(3)])

            headBuyPrice = sorted(
                [item[0] for item in Counter(buyPriceSorted).most_common(3)])
            headBuyTpPrice = sorted(
                [item[0] for item in Counter(buyTpPriceSorted).most_common(3)])
            headBuySpPrice = sorted(
                [item[0] for item in Counter(buySpPriceSorted).most_common(3)])

            self.coreResult = self.coreStrategy(self.sqlite.query_many(
                "SELECT id,strategy FROM article_table WHERE strategy != ''"))

            strategyList.append({
                "buy": {
                    "price": headBuyPrice,
                    "sp": headBuySpPrice,
                    "tp": headBuyTpPrice,
                },
                "sell": {
                    "price": headSellPrice,
                    "sp": headSellSpPrice,
                    "tp": headSellTpPrice,
                },
                "main": self.coreResult,
            })
            saveLog("网络策略获取结果：" + str(strategyList))

            timeNow = datetime.datetime.now().hour
            if timeNow in self.timePoint or (timeNow not in self.timePoint and self.coreResult is not None):
                sendMail("最新策略发布，请及时查看", str(strategyList), timer=False)

    def immediatelyTrade(self, article, articleTime):
        """
        现价单
        """
        for item in self.immediately:
            result = re.search(item, article, re.S)
            if result:
                child = re.search("\d{4}", result.group(), re.S)
                if child and current_time()-articleTime < getImmediatelyTime():
                    # immediatelyTag
                    priceValue = int(child.group())
                    sendMail(result.group())
                    saveLog(result.group())

    def updateRecord(self):
        """
        更新记录表
        """
        recordMaxTime = 0
        recordNewestTime = self.sqlite.query_many(
            "SELECT MAX(time) FROM record_table")

        if recordNewestTime != None and len(recordNewestTime) != 0 and recordNewestTime[0] != None and recordNewestTime[0][0] != None:
            recordMaxTime = recordNewestTime[0][0]

        articleList = self.sqlite.query_many(
            "SELECT id,url,article,strategy,viewpoint,time FROM article_table WHERE time > "+str(recordMaxTime))

        recordMaxId = self.sqlite.query_one(
            "SELECT MAX(id) FROM record_table")

        if len(recordMaxId) != 0 and recordMaxId[0] != None and recordMaxId != None:
            recordMaxId = recordMaxId[0]
        else:
            recordMaxId = 0

        for item in articleList:
            recordMaxId = recordMaxId+1
            self.sqlite.operate_one(
                'insert into record_table values (?,?,?,?,?,?)',
                (recordMaxId, item[1], item[2], item[3], item[4], str(item[5])))

    def formatePriceList(self, article):
        """
        剔除不符合规范的价格
        """
        for child in article:
            sellIndex = [
                index for index in range(0, len(child))
                if "sell" in child[index]
            ]
            buyIndex = [
                index for index in range(0, len(child))
                if "buy" in child[index]
            ]

            if len(sellIndex) != 0:
                sellInfo = child[sellIndex[0]]
                splitSell = [int(item) for item in sellInfo["sell"].split("、")]
                if "sp" in sellInfo and sellInfo["sp"] != "":
                    spValue = [int(item) for item in sellInfo["sp"].split("、")]
                    if all(a < b for a, b in zip(splitSell, spValue)) is False:
                        sellInfo.pop("sp")
                if "tp" in sellInfo and sellInfo["tp"] != "":
                    spliteTp = [
                        int(item) for item in sellInfo["tp"].split("、")
                    ]
                    if all(b < a
                           for a, b in zip(splitSell, spliteTp)) is False:
                        sellInfo.pop("tp")

            if len(buyIndex) != 0:
                buyInfo = child[buyIndex[0]]
                splitBuy = [int(item) for item in buyInfo["buy"].split("、")]
                if "sp" in buyInfo and buyInfo["sp"] != "":
                    spValue = [int(item) for item in buyInfo["sp"].split("、")]
                    if all(b < a for a, b in zip(splitBuy, spValue)) is False:
                        buyInfo.pop("sp")
                if "tp" in buyInfo and buyInfo["tp"] != "":
                    spliteTp = [int(item) for item in buyInfo["tp"].split("、")]
                    if all(a < b for a, b in zip(splitBuy, spliteTp)) is False:
                        buyInfo.pop("tp")
        return article

    def hasNewArticle(self):
        """
        是否爬到新文章
        """
        newArticle = self.sqlite.query_many(
            "SELECT * FROM article_table WHERE time > "+str(self.startTime))
        if newArticle is not None and len(newArticle) != 0:
            return True
        return False

    def formatePrice(self, source):
        """
        获取价格
        """
        result = re.compile(r'\d{4}').findall(source)
        if len(result) != 0:
            return "、".join(result)
        return ""

    def getArticleTime(self):
        zeroStamp = 0
        articleList = self.sqlite.query_one(
            "SELECT MAX(time) FROM article_table")

        if len(articleList) != 0 and articleList[0] != None:
            zeroStamp = articleList[0]
        else:
            zeroStamp = today_hour_stamp(hour=6)
        return zeroStamp

    def initSingal(self):
        """
        初始化信号
        """
        if len(strategyList) != 0:
            strategyList.clear()

        if len(mvSingal) != 0:
            mvSingal.clear()

        if len(indicatorSignal) != 0:
            indicatorSignal.clear()

    def isHasStrategy(self):
        """
        主策略是否存在
        """
        if len(strategyList) == 0 or strategyList == None or "main" not in strategyList[0] or strategyList[0]["main"] == None:
            return False
        return True

    def wenxinContent(self, lenth=None):
        """
        创建文心一言提交内容
        """
        wenxinContent = ""
        resultStrategy = self.regularViewpoint()
        if lenth != None:
            if len(resultStrategy) < lenth:
                lenth = len(resultStrategy)
        else:
            lenth = len(resultStrategy)

        for index in range(0, lenth):
            childContent = "策略："
            child = resultStrategy[index]
            sellIndex = [
                index for index in range(0, len(child))
                if "sell" in child[index]
            ]
            buyIndex = [
                index for index in range(0, len(child))
                if "buy" in child[index]
            ]

            if len(sellIndex) != 0:
                sellInfo = child[sellIndex[0]]
                if "sell" in sellInfo:
                    childContent = childContent + "空单：" + sellInfo[
                        "sell"] + "入场，"
                    if "sp" in sellInfo:
                        childContent = childContent + "止损点：" + sellInfo[
                            "sp"] + "，"
                    if "tp" in sellInfo:
                        childContent = childContent + "止盈点：" + sellInfo[
                            "tp"] + "；"

            if len(buyIndex) != 0:
                buyInfo = child[buyIndex[0]]
                if "buy" in buyInfo:
                    childContent = childContent + \
                        "多单：" + buyInfo["buy"] + "入场，"
                    if "sp" in buyInfo:
                        childContent = childContent + "止损点：" + buyInfo[
                            "sp"] + "，"
                    if "tp" in buyInfo:
                        childContent = childContent + "止盈点：" + buyInfo[
                            "tp"] + "。"
            wenxinContent = wenxinContent + "" + str(
                index + 1) + "、" + childContent + "\n"
        return wenxinContent

    def commitRobot(self):
        """
        调用文心一言
        """
        result = self.wenxinContent(lenth=10)
        wxResult = self.qianfan.sendRequest(result)
        value = wxResult["result"]
        print("")
